{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": true,
    "deletable": true,
    "editable": true
   },
   "outputs": [],
   "source": [
    "import os,sys,inspect\n",
    "import os\n",
    "import joblib\n",
    "import tensorflow as tf\n",
    "import numpy as np\n",
    "import h5py\n",
    "import scipy.sparse.linalg as la\n",
    "import scipy.sparse as sp\n",
    "import scipy\n",
    "import time\n",
    "\n",
    "import matplotlib.pyplot as plt\n",
    "from matplotlib.backends.backend_pdf import PdfPages\n",
    "%matplotlib inline"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": true,
    "deletable": true,
    "editable": true
   },
   "outputs": [],
   "source": [
    "#for simplicity I start with the first split\n",
    "path_dataset = '../../datasets/yahoo_music/training_test_dataset_10_NNs.mat'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": true,
    "deletable": true,
    "editable": true
   },
   "outputs": [],
   "source": [
    "# auxiliary functions:\n",
    "\n",
    "# import matlab files in python\n",
    "def load_matlab_file(path_file, name_field):\n",
    "    \"\"\"\n",
    "    load '.mat' files\n",
    "    inputs:\n",
    "        path_file, string containing the file path\n",
    "        name_field, string containig the field name (default='shape')\n",
    "    warning:\n",
    "        '.mat' files should be saved in the '-v7.3' format\n",
    "    \"\"\"\n",
    "    db = h5py.File(path_file, 'r')\n",
    "    ds = db[name_field]\n",
    "    try:\n",
    "        if 'ir' in ds.keys():\n",
    "            data = np.asarray(ds['data'])\n",
    "            ir   = np.asarray(ds['ir'])\n",
    "            jc   = np.asarray(ds['jc'])\n",
    "            out  = sp.csc_matrix((data, ir, jc)).astype(np.float32)\n",
    "    except AttributeError:\n",
    "        # Transpose in case is a dense matrix because of the row- vs column- major ordering between python and matlab\n",
    "        out = np.asarray(ds).astype(np.float32).T\n",
    "\n",
    "    db.close()\n",
    "\n",
    "    return out"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'#definition of the ground truth and of the training set\\nMgt = M; # Ground truth\\nMtraining = np.multiply(Otraining, Mgt); #Training matrix\\nMtest = np.multiply(Otest, Mgt); #Test matrix (i.e. matrix containing ONLY the elements where we want to check our\\n                                 #reconstruction quality. It does not intersect with the Mtraining matrix)'"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#loading of the required matrices\n",
    "M = load_matlab_file(path_dataset, 'M')\n",
    "Otraining = load_matlab_file(path_dataset, 'Otraining')\n",
    "Otest = load_matlab_file(path_dataset, 'Otest')\n",
    "Wcol = load_matlab_file(path_dataset, 'W_tracks') #dense\n",
    "#Wcol = load_matlab_file(path_dataset, 'W_movies') #dense\n",
    "\n",
    "\"\"\"#definition of the ground truth and of the training set\n",
    "Mgt = M; # Ground truth\n",
    "Mtraining = np.multiply(Otraining, Mgt); #Training matrix\n",
    "Mtest = np.multiply(Otest, Mgt); #Test matrix (i.e. matrix containing ONLY the elements where we want to check our\n",
    "                                 #reconstruction quality. It does not intersect with the Mtraining matrix)\"\"\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Num data samples: 2401\n",
      "Num train samples: 2401\n",
      "Num train+data samples: 4802\n"
     ]
    }
   ],
   "source": [
    "np.random.seed(0)\n",
    "pos_tr_samples = np.where(Otraining)\n",
    "\n",
    "num_tr_samples = len(pos_tr_samples[0])\n",
    "list_idx = range(num_tr_samples)\n",
    "np.random.shuffle(list_idx)\n",
    "idx_data = list_idx[:num_tr_samples//2]\n",
    "idx_train = list_idx[num_tr_samples//2:]\n",
    "\n",
    "pos_data_samples = (pos_tr_samples[0][idx_data], pos_tr_samples[1][idx_data])\n",
    "pos_tr_samples = (pos_tr_samples[0][idx_train], pos_tr_samples[1][idx_train])\n",
    "\n",
    "Odata = np.zeros(M.shape)\n",
    "Otraining = np.zeros(M.shape)\n",
    "\n",
    "for k in range(len(pos_data_samples[0])):\n",
    "    Odata[pos_data_samples[0][k], pos_data_samples[1][k]] = 1\n",
    "    \n",
    "for k in range(len(pos_tr_samples[0])):\n",
    "    Otraining[pos_tr_samples[0][k], pos_tr_samples[1][k]] = 1\n",
    "    \n",
    "print 'Num data samples: %d' % (np.sum(Odata),)\n",
    "print 'Num train samples: %d' % (np.sum(Otraining),)\n",
    "print 'Num train+data samples: %d' % (np.sum(Odata+Otraining),)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [],
   "source": [
    "#computation of the normalized laplacians\n",
    "Lcol = sp.csgraph.laplacian(Wcol, normed=True) #ATTENTION! Here we do not consider self-rings in the laplacian computation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(3000, 3000)\n",
      "(3000,)\n",
      "(3000, 3000)\n"
     ]
    }
   ],
   "source": [
    "#apply SVD initially for detecting the main components of our initialization\n",
    "U, s, V = np.linalg.svd(Odata*M, full_matrices=0)\n",
    "\n",
    "print U.shape\n",
    "print s.shape\n",
    "print V.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(3000, 10)\n",
      "(3000, 10)\n"
     ]
    }
   ],
   "source": [
    "rank_W_H = 10\n",
    "partial_s = s[:rank_W_H]\n",
    "partial_S_sqrt = np.diag(np.sqrt(partial_s))\n",
    "initial_W = np.dot(U[:, :rank_W_H], partial_S_sqrt)\n",
    "initial_H = np.dot(partial_S_sqrt, V[:rank_W_H, :]).T\n",
    "\n",
    "print initial_W.shape\n",
    "print initial_H.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Original training matrix\n",
      "Reconstructed trainign matrix\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "<matplotlib.colorbar.Colorbar at 0x7fd15c7f4210>"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\nRK5CYII=\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7fd1d448ca90>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7fd15c83f690>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "print 'Original training matrix'\n",
    "plt.figure()\n",
    "plt.imshow(Odata*M)\n",
    "plt.colorbar()\n",
    "\n",
    "print 'Reconstructed trainign matrix'\n",
    "plt.figure()\n",
    "plt.imshow(np.dot(initial_W, initial_H.T))\n",
    "plt.colorbar()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [],
   "source": [
    "class Train_test_matrix_completion:\n",
    "    \n",
    "    \"\"\"\n",
    "    The neural network model.\n",
    "    \"\"\"\n",
    "    \n",
    "    def frobenius_norm(self, tensor):\n",
    "        square_tensor = tf.square(tensor)\n",
    "        tensor_sum = tf.reduce_sum(square_tensor)\n",
    "        frobenius_norm = tf.sqrt(tensor_sum)\n",
    "        return frobenius_norm\n",
    "    \n",
    "    def chebyshev_polynomials(self, x, n): #compute the chebyshev polynomial of order n of a potentially N-dimensional tensor \n",
    "        #assuming x is N-dimensional\n",
    "        if (n==0):\n",
    "            return tf.cast(tf.diag(tf.ones([tf.shape(x)[0],])), 'float32')\n",
    "        elif (n==1):\n",
    "            return tf.cast(x, 'float32')\n",
    "        else:\n",
    "            return 2*tf.matmul(x, self.chebyshev_polynomials(x, n - 1))  - self.chebyshev_polynomials(x, n - 2)\n",
    "        \n",
    "    def chebyshev_polynomials_mul(self, L, x, n): #compute the chebyshev polynomial of order n of a potentially N-dimensional tensor \n",
    "        #assuming x is N-dimensional\n",
    "        if (n==0):\n",
    "            return x\n",
    "        elif (n==1):\n",
    "            return tf.sparse_tensor_dense_matmul(L, x)\n",
    "        else:\n",
    "            return 2*tf.sparse_tensor_dense_matmul(L, self.chebyshev_polynomials_mul(L, x, n - 1))  - self.chebyshev_polynomials_mul(L, x, n - 2)\n",
    "    \n",
    "    def convert_coo_to_sparse_tensor(self, L):\n",
    "        indices = np.column_stack((L.row, L.col))\n",
    "        L = tf.SparseTensor(indices, L.data, L.shape)\n",
    "        L = tf.sparse_reorder(L)\n",
    "        return L\n",
    "    \n",
    "    def softmax(self, A, dim):\n",
    "        A = tf.exp(A - tf.reduce_max(A, reduction_indices=dim, keep_dims=True))\n",
    "        return A/tf.reduce_sum(A, reduction_indices=dim, keep_dims=True)\n",
    "    \n",
    "    def mono_conv(self, list_lap, ord_conv, A, W, b):\n",
    "        \n",
    "        feat = []\n",
    "        #collect features\n",
    "        for k in range(ord_conv):\n",
    "            c_lap = list_lap[k] \n",
    "                                                     \n",
    "            #dense implementation\n",
    "            c_feat = tf.matmul(c_lap, A, a_is_sparse=False)\n",
    "            feat.append(c_feat)\n",
    "            \n",
    "        all_feat = tf.concat(1, feat)\n",
    "        conv_feat = tf.matmul(all_feat, W) + b\n",
    "        conv_feat = tf.nn.relu(conv_feat)\n",
    "        \n",
    "        return conv_feat\n",
    "    \n",
    "    def compute_cheb_polynomials_sparse(self, L, ord_cheb, list_cheb):\n",
    "        list_dense = list()\n",
    "        for k in range(ord_cheb):\n",
    "            if (k==0):\n",
    "                mat = tf.diag(tf.ones([tf.shape(L)[0],]))\n",
    "                list_dense.append(mat)\n",
    "                idx = tf.where(tf.not_equal(mat, 0))\n",
    "                # Use tf.shape(a_t, out_type=tf.int64) instead of a_t.get_shape() if tensor shape is dynamic\n",
    "                sparse = tf.SparseTensor(idx, tf.gather_nd(mat, idx), tf.shape(mat, out_type=tf.int64))\n",
    "                list_cheb.append(sparse)\n",
    "            elif (k==1):\n",
    "                mat = L\n",
    "                list_dense.append(mat)\n",
    "                idx = tf.where(tf.not_equal(mat, 0))\n",
    "                # Use tf.shape(a_t, out_type=tf.int64) instead of a_t.get_shape() if tensor shape is dynamic\n",
    "                sparse = tf.SparseTensor(idx, tf.gather_nd(mat, idx), tf.shape(mat, out_type=tf.int64))\n",
    "                list_cheb.append(sparse)\n",
    "            else:\n",
    "                mat = 2*tf.matmul(L, list_dense[k-1])  - list_dense[k-2]\n",
    "                list_dense.append(mat)\n",
    "                idx = tf.where(tf.not_equal(mat, 0))\n",
    "                # Use tf.shape(a_t, out_type=tf.int64) instead of a_t.get_shape() if tensor shape is dynamic\n",
    "                sparse = tf.SparseTensor(idx, tf.gather_nd(mat, idx), tf.shape(mat, out_type=tf.int64))\n",
    "                list_cheb.append(sparse)\n",
    "                \n",
    "    def compute_cheb_polynomials(self, L, ord_cheb, list_cheb):\n",
    "        for k in range(ord_cheb):\n",
    "            if (k==0):\n",
    "                list_cheb.append(tf.cast(tf.diag(tf.ones([tf.shape(L)[0],])), 'float32'))\n",
    "            elif (k==1):\n",
    "                list_cheb.append(tf.cast(L, 'float32'))\n",
    "            else:\n",
    "                list_cheb.append(2*tf.matmul(L, list_cheb[k-1])  - list_cheb[k-2])\n",
    "                \n",
    "    def compute_feat_single_graph_factorized_mat(self, A, B, W_conv, b_conv, list_lap, ord_cheb, relu=1):\n",
    "        feat = []\n",
    "        #collect features\n",
    "        for k in range(ord_cheb):\n",
    "            c_lap = list_lap[k]\n",
    "                                                     \n",
    "            #dense implementation\n",
    "            c_feat_B = tf.matmul(B, c_lap, transpose_a=True) # r x m\n",
    "            c_feat = tf.matmul(A, c_feat_B) #n x m\n",
    "            \n",
    "            feat.append(c_feat)\n",
    "            \n",
    "        all_feat = tf.pack(feat, 2) #n x m x ord_cheb\n",
    "        all_feat = tf.reshape(all_feat, [-1, ord_cheb]) #n*m x ord_cheb\n",
    "        conv_feat = tf.matmul(all_feat, W_conv) + b_conv #n*m x conv_feat\n",
    "        if (relu==1):\n",
    "            conv_feat = tf.nn.relu(conv_feat)\n",
    "        conv_feat = tf.reshape(conv_feat, [tf.shape(A)[0], tf.shape(B)[0], tf.shape(W_conv)[1]]) #n x m x conv_feat \n",
    "        return conv_feat #n x m x conv_feat \n",
    "    \n",
    "    def compute_feat_single_graph(self, A, W_conv, b_conv, list_lap, ord_cheb, relu=1):\n",
    "        feat = []\n",
    "        #collect features\n",
    "        for k in range(ord_cheb):\n",
    "            c_lap = list_lap[k]\n",
    "                                                     \n",
    "            #dense implementation\n",
    "            c_feat = tf.matmul(c_lap, A, transpose_a=True) # n x f\n",
    "            \n",
    "            feat.append(c_feat)\n",
    "            \n",
    "        all_feat = tf.pack(feat, 2) #n x f x ord_cheb\n",
    "        all_feat = tf.reshape(all_feat, [-1, tf.shape(all_feat)[1]*ord_cheb]) #n x f*ord_cheb\n",
    "        conv_feat = tf.matmul(all_feat, W_conv) + b_conv #n x conv_feat\n",
    "        if (relu==1):\n",
    "            conv_feat = tf.nn.relu(conv_feat)\n",
    "        return conv_feat #n x conv_feat\n",
    "        \n",
    "    \n",
    "    def __init__(self, M, Lc, Odata, Otraining, Otest, initial_W, initial_H,\n",
    "                 order_chebyshev_col = 5,\n",
    "                 num_iterations = 10, gamma=1.0, gamma_W=1.0, learning_rate=1e-4, idx_gpu = '/gpu:1'):\n",
    "        \n",
    "        #order of the spectral filters\n",
    "        self.ord_col = order_chebyshev_col\n",
    "        self.num_iterations = num_iterations\n",
    "        self.n_conv_feat = 32\n",
    "        \n",
    "        with tf.Graph().as_default() as g:\n",
    "                tf.logging.set_verbosity(tf.logging.ERROR)\n",
    "                self.graph = g\n",
    "                tf.set_random_seed(0)\n",
    "                with tf.device(idx_gpu):\n",
    "                    \n",
    "                        #loading of the laplacians\n",
    "                        self.Lc = tf.cast(Lc, 'float32')\n",
    "                        \n",
    "                        self.norm_Lc = self.Lc - tf.diag(tf.ones([Lc.shape[0], ]))\n",
    "                        \n",
    "                        #compute all chebyshev polynomials a priori\n",
    "                        self.list_col_cheb_pol = list()\n",
    "                        self.compute_cheb_polynomials(self.norm_Lc, self.ord_col, self.list_col_cheb_pol)\n",
    "                        \n",
    "                        #definition of constant matrices\n",
    "                        self.M = tf.constant(M, dtype=tf.float32)\n",
    "                        self.Odata = tf.constant(Odata, dtype=tf.float32)\n",
    "                        self.Otraining = tf.constant(Otraining, dtype=tf.float32) #training mask\n",
    "                        self.Otest = tf.constant(Otest, dtype=tf.float32) #test mask\n",
    "                         \n",
    "                        ##################################definition of the NN variables#####################################\n",
    "                        \n",
    "                        #definition of the weights for extracting the global features\n",
    "                        self.W_conv_H = tf.get_variable(\"W_conv_H\", shape=[self.ord_col*initial_W.shape[1], self.n_conv_feat], initializer=tf.contrib.layers.xavier_initializer())\n",
    "                        self.b_conv_H = tf.Variable(tf.zeros([self.n_conv_feat,]))\n",
    "                        \n",
    "                        #recurrent N parameters\n",
    "                        self.W_f_t = tf.get_variable(\"W_f_t\", shape=[self.n_conv_feat, self.n_conv_feat], initializer=tf.contrib.layers.xavier_initializer())\n",
    "                        self.W_i_t = tf.get_variable(\"W_i_t\", shape=[self.n_conv_feat, self.n_conv_feat], initializer=tf.contrib.layers.xavier_initializer())\n",
    "                        self.W_o_t = tf.get_variable(\"W_o_t\", shape=[self.n_conv_feat, self.n_conv_feat], initializer=tf.contrib.layers.xavier_initializer())\n",
    "                        self.W_c_t = tf.get_variable(\"W_c_t\", shape=[self.n_conv_feat, self.n_conv_feat], initializer=tf.contrib.layers.xavier_initializer())\n",
    "                        self.U_f_t = tf.get_variable(\"U_f_t\", shape=[self.n_conv_feat, self.n_conv_feat], initializer=tf.contrib.layers.xavier_initializer())\n",
    "                        self.U_i_t = tf.get_variable(\"U_i_t\", shape=[self.n_conv_feat, self.n_conv_feat], initializer=tf.contrib.layers.xavier_initializer())\n",
    "                        self.U_o_t = tf.get_variable(\"U_o_t\", shape=[self.n_conv_feat, self.n_conv_feat], initializer=tf.contrib.layers.xavier_initializer())\n",
    "                        self.U_c_t = tf.get_variable(\"U_c_t\", shape=[self.n_conv_feat, self.n_conv_feat], initializer=tf.contrib.layers.xavier_initializer())\n",
    "                        self.b_f_t = tf.Variable(tf.zeros([self.n_conv_feat,]))\n",
    "                        self.b_i_t = tf.Variable(tf.zeros([self.n_conv_feat,]))\n",
    "                        self.b_o_t = tf.Variable(tf.zeros([self.n_conv_feat,]))\n",
    "                        self.b_c_t = tf.Variable(tf.zeros([self.n_conv_feat,]))\n",
    "                        \n",
    "                        #output parameters\n",
    "                        self.W_out_H = tf.get_variable(\"W_out_H\", shape=[self.n_conv_feat, initial_H.shape[1]], initializer=tf.contrib.layers.xavier_initializer()) \n",
    "                        self.b_out_H = tf.Variable(tf.zeros([initial_H.shape[1],]))\n",
    "                        \n",
    "                        #########definition of the NN\n",
    "                        #definition of W and H\n",
    "                        self.W = tf.Variable(initial_W.astype('float32'))\n",
    "                        self.H = tf.constant(initial_H.astype('float32'))\n",
    "                        \n",
    "                        self.X = tf.matmul(self.W, self.H, transpose_b=True) #we may initialize it at random here\n",
    "                        self.list_X = list()\n",
    "                        self.list_X.append(tf.identity(self.X))\n",
    "                        #self.X = tf.reshape(self.X, [-1,])\n",
    "                        \n",
    "                        #RNN\n",
    "                        self.h_t = tf.zeros([M.shape[0], self.n_conv_feat])\n",
    "                        self.c_t = tf.zeros([M.shape[0], self.n_conv_feat])\n",
    "                        \n",
    "                        \n",
    "                        for k in range(self.num_iterations):\n",
    "                            #extraction of global features vectors\n",
    "                            self.final_feat_tracks = self.mono_conv(self.list_col_cheb_pol, self.ord_col, self.H, self.W_conv_H, self.b_conv_H)\n",
    "                            \n",
    "                            #here we have to split the features between users and movies LSTMs\n",
    "                            \n",
    "                            #users RNN\n",
    "                            self.f_t = tf.sigmoid(tf.matmul(self.final_feat_tracks, self.W_f_t) + tf.matmul(self.h_t, self.U_f_t) + self.b_f_t)\n",
    "                            self.i_t = tf.sigmoid(tf.matmul(self.final_feat_tracks, self.W_i_t) + tf.matmul(self.h_t, self.U_i_t) + self.b_i_t)\n",
    "                            self.o_t = tf.sigmoid(tf.matmul(self.final_feat_tracks, self.W_o_t) + tf.matmul(self.h_t, self.U_o_t) + self.b_o_t)\n",
    "                            \n",
    "                            self.update_c_t = tf.sigmoid(tf.matmul(self.final_feat_tracks, self.W_c_t) + tf.matmul(self.h_t, self.U_c_t) + self.b_c_t)\n",
    "                            self.c_t = tf.mul(self.f_t, self.c_t) + tf.mul(self.i_t, self.update_c_t)\n",
    "                            self.h_t = tf.mul(self.o_t, tf.sigmoid(self.c_t))\n",
    "                            \n",
    "                            #compute update of matrix X\n",
    "                            self.delta_H = tf.tanh(tf.matmul(self.c_t, self.W_out_H) + self.b_out_H) #N x rank_W_H\n",
    "                            \n",
    "                            self.H += self.delta_H\n",
    "                        \n",
    "                            self.X = tf.matmul(self.W, self.H, transpose_b=True)\n",
    "                            self.list_X.append(tf.identity(tf.reshape(self.X, [tf.shape(self.M)[0], tf.shape(self.M)[1]])))\n",
    "                        self.X = tf.matmul(self.W, self.H, transpose_b=True)\n",
    "                        #########loss definition\n",
    "                        \n",
    "                        #computation of the accuracy term\n",
    "                        self.norm_X = 1+99*(self.X-tf.reduce_min(self.X))/(tf.reduce_max(self.X-tf.reduce_min(self.X)))\n",
    "                        frob_tensor = tf.mul(self.Otraining + self.Odata, self.norm_X - M)\n",
    "                        self.loss_frob = tf.square(self.frobenius_norm(frob_tensor))/np.sum(Otraining+Odata)\n",
    "                        \n",
    "                        #computation of the regularization terms\n",
    "                        trace_col_tensor = tf.matmul(tf.matmul(self.X, self.Lc), self.X, transpose_b=True)\n",
    "                        self.loss_trace_col = tf.trace(trace_col_tensor)/tf.cast(tf.shape(self.X)[0]*tf.shape(self.X)[1],'float32')\n",
    "                        \n",
    "                        self.frob_norm_W = tf.square(self.frobenius_norm(self.W))/tf.cast(tf.shape(self.W)[0]*tf.shape(self.W)[1], 'float32')\n",
    "                        \n",
    "                        \n",
    "                        #training loss definition\n",
    "                        self.loss = self.loss_frob + (gamma/2)*self.loss_trace_col + (gamma_W/2)*self.frob_norm_W\n",
    "                        \n",
    "                        #test loss definition\n",
    "                        self.predictions = tf.mul(self.Otest, self.norm_X - self.M)\n",
    "                        self.predictions_error = self.frobenius_norm(self.predictions)\n",
    "\n",
    "                        #definition of the solver\n",
    "                        self.optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(self.loss)\n",
    "                        \n",
    "                        self.var_grad = tf.gradients(self.loss, tf.trainable_variables())\n",
    "                        self.norm_grad = self.frobenius_norm(tf.concat(0, [tf.reshape(g, [-1]) for g in self.var_grad]))\n",
    "\n",
    "                        # Create a session for running Ops on the Graph.\n",
    "                        config = tf.ConfigProto(allow_soft_placement = True)\n",
    "                        config.gpu_options.allow_growth = True\n",
    "                        self.session = tf.Session(config=config)\n",
    "\n",
    "                        # Run the Op to initialize the variables.\n",
    "                        init = tf.initialize_all_variables()\n",
    "                        self.session.run(init)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true,
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[TRN] iter = 000, cost = 2.63e+03, |grad| = 8.55e+03 (1.35e+00s)\n",
      "[TST] iter = 000, cost = 713.655090, RMSE = 30.911833 (0.51s)\n",
      "[TRN] iter = 100, cost = 5.14e+02, |grad| = 3.49e+02 (7.29e-01s)\n",
      "[TST] iter = 100, cost = 515.934814, RMSE = 22.347616 (0.30s)\n",
      "[TRN] iter = 200, cost = 4.93e+02, |grad| = 4.80e+02 (7.54e-01s)\n",
      "[TST] iter = 200, cost = 519.223022, RMSE = 22.490046 (0.30s)\n",
      "[TRN] iter = 300, cost = 4.76e+02, |grad| = 7.93e+01 (7.74e-01s)\n",
      "[TST] iter = 300, cost = 518.208801, RMSE = 22.446115 (0.27s)\n",
      "[TRN] iter = 400, cost = 4.76e+02, |grad| = 9.92e+02 (7.31e-01s)\n",
      "[TST] iter = 400, cost = 514.524170, RMSE = 22.286516 (0.32s)\n",
      "[TRN] iter = 500, cost = 4.46e+02, |grad| = 1.45e+02 (7.62e-01s)\n",
      "[TST] iter = 500, cost = 518.861389, RMSE = 22.474382 (0.31s)\n",
      "[TRN] iter = 600, cost = 4.44e+02, |grad| = 1.84e+02 (8.13e-01s)\n",
      "[TST] iter = 600, cost = 510.932434, RMSE = 22.130941 (0.29s)\n",
      "[TRN] iter = 700, cost = 4.23e+02, |grad| = 2.22e+02 (7.65e-01s)\n",
      "[TST] iter = 700, cost = 513.564270, RMSE = 22.244938 (0.27s)\n",
      "[TRN] iter = 800, cost = 4.10e+02, |grad| = 1.16e+02 (7.87e-01s)\n",
      "[TST] iter = 800, cost = 513.953735, RMSE = 22.261808 (0.28s)\n",
      "[TRN] iter = 900, cost = 3.95e+02, |grad| = 3.60e+02 (7.57e-01s)\n",
      "[TST] iter = 900, cost = 513.104797, RMSE = 22.225035 (0.29s)\n",
      "[TRN] iter = 1000, cost = 3.87e+02, |grad| = 4.27e+02 (7.44e-01s)\n",
      "[TST] iter = 1000, cost = 512.803101, RMSE = 22.211969 (0.28s)\n",
      "[TRN] iter = 1100, cost = 3.76e+02, |grad| = 2.76e+02 (7.84e-01s)\n",
      "[TST] iter = 1100, cost = 509.049927, RMSE = 22.049400 (0.30s)\n",
      "[TRN] iter = 1200, cost = 3.65e+02, |grad| = 1.13e+02 (7.70e-01s)\n",
      "[TST] iter = 1200, cost = 506.425079, RMSE = 21.935705 (0.31s)\n",
      "[TRN] iter = 1300, cost = 3.57e+02, |grad| = 3.12e+02 (7.45e-01s)\n",
      "[TST] iter = 1300, cost = 507.303955, RMSE = 21.973774 (0.28s)\n",
      "[TRN] iter = 1400, cost = 3.53e+02, |grad| = 2.71e+02 (7.57e-01s)\n",
      "[TST] iter = 1400, cost = 502.844696, RMSE = 21.780621 (0.28s)\n",
      "[TRN] iter = 1500, cost = 4.73e+02, |grad| = 7.19e+02 (7.97e-01s)\n",
      "[TST] iter = 1500, cost = 509.455475, RMSE = 22.066965 (0.27s)\n",
      "[TRN] iter = 1600, cost = 3.62e+02, |grad| = 1.89e+02 (7.71e-01s)\n",
      "[TST] iter = 1600, cost = 500.496124, RMSE = 21.678894 (0.29s)\n",
      "[TRN] iter = 1700, cost = 3.44e+02, |grad| = 4.70e+02 (7.65e-01s)\n",
      "[TST] iter = 1700, cost = 499.791077, RMSE = 21.648355 (0.27s)\n",
      "[TRN] iter = 1800, cost = 3.46e+02, |grad| = 6.77e+02 (7.60e-01s)\n",
      "[TST] iter = 1800, cost = 503.336670, RMSE = 21.801931 (0.28s)\n",
      "[TRN] iter = 1900, cost = 3.29e+02, |grad| = 4.05e+02 (7.96e-01s)\n",
      "[TST] iter = 1900, cost = 501.528046, RMSE = 21.723591 (0.28s)\n",
      "[TRN] iter = 2000, cost = 3.25e+02, |grad| = 6.21e+02 (7.70e-01s)\n",
      "[TST] iter = 2000, cost = 499.407135, RMSE = 21.631723 (0.29s)\n",
      "[TRN] iter = 2100, cost = 3.21e+02, |grad| = 4.45e+02 (7.62e-01s)\n",
      "[TST] iter = 2100, cost = 500.673065, RMSE = 21.686558 (0.26s)\n",
      "[TRN] iter = 2200, cost = 3.22e+02, |grad| = 5.89e+02 (7.10e-01s)\n",
      "[TST] iter = 2200, cost = 501.714905, RMSE = 21.731684 (0.29s)\n",
      "[TRN] iter = 2300, cost = 3.14e+02, |grad| = 1.22e+03 (7.52e-01s)\n",
      "[TST] iter = 2300, cost = 500.020691, RMSE = 21.658300 (0.27s)\n",
      "[TRN] iter = 2400, cost = 3.11e+02, |grad| = 4.32e+02 (7.48e-01s)\n",
      "[TST] iter = 2400, cost = 505.771118, RMSE = 21.907379 (0.27s)\n",
      "[TRN] iter = 2500, cost = 3.05e+02, |grad| = 1.12e+03 (6.97e-01s)\n",
      "[TST] iter = 2500, cost = 498.166901, RMSE = 21.578005 (0.26s)\n",
      "[TRN] iter = 2600, cost = 3.11e+02, |grad| = 3.43e+02 (6.92e-01s)\n",
      "[TST] iter = 2600, cost = 500.014313, RMSE = 21.658024 (0.30s)\n",
      "[TRN] iter = 2700, cost = 2.99e+02, |grad| = 3.22e+02 (7.22e-01s)\n",
      "[TST] iter = 2700, cost = 500.996521, RMSE = 21.700569 (0.28s)\n",
      "[TRN] iter = 2800, cost = 2.96e+02, |grad| = 1.15e+03 (6.84e-01s)\n",
      "[TST] iter = 2800, cost = 500.613312, RMSE = 21.683969 (0.29s)\n",
      "[TRN] iter = 2900, cost = 2.96e+02, |grad| = 9.59e+02 (6.80e-01s)\n",
      "[TST] iter = 2900, cost = 507.438232, RMSE = 21.979589 (0.26s)\n",
      "[TRN] iter = 3000, cost = 2.89e+02, |grad| = 3.74e+02 (6.73e-01s)\n",
      "[TST] iter = 3000, cost = 498.499298, RMSE = 21.592402 (0.26s)\n",
      "[TRN] iter = 3100, cost = 3.20e+02, |grad| = 1.13e+03 (6.82e-01s)\n",
      "[TST] iter = 3100, cost = 494.321533, RMSE = 21.411442 (0.27s)\n",
      "[TRN] iter = 3200, cost = 2.91e+02, |grad| = 1.89e+03 (6.68e-01s)\n",
      "[TST] iter = 3200, cost = 499.272400, RMSE = 21.625887 (0.27s)\n",
      "[TRN] iter = 3300, cost = 2.84e+02, |grad| = 8.40e+02 (6.81e-01s)\n",
      "[TST] iter = 3300, cost = 501.157410, RMSE = 21.707537 (0.27s)\n",
      "[TRN] iter = 3400, cost = 2.87e+02, |grad| = 1.12e+03 (6.76e-01s)\n",
      "[TST] iter = 3400, cost = 503.033661, RMSE = 21.788807 (0.25s)\n",
      "[TRN] iter = 3500, cost = 2.81e+02, |grad| = 4.41e+02 (6.54e-01s)\n",
      "[TST] iter = 3500, cost = 495.655151, RMSE = 21.469208 (0.24s)\n",
      "[TRN] iter = 3600, cost = 2.78e+02, |grad| = 7.24e+02 (6.67e-01s)\n",
      "[TST] iter = 3600, cost = 499.947571, RMSE = 21.655132 (0.24s)\n",
      "[TRN] iter = 3700, cost = 2.74e+02, |grad| = 8.96e+02 (6.78e-01s)\n",
      "[TST] iter = 3700, cost = 494.441498, RMSE = 21.416637 (0.25s)\n",
      "[TRN] iter = 3800, cost = 2.69e+02, |grad| = 6.47e+02 (6.83e-01s)\n",
      "[TST] iter = 3800, cost = 499.316437, RMSE = 21.627796 (0.25s)\n",
      "[TRN] iter = 3900, cost = 2.70e+02, |grad| = 1.60e+03 (6.91e-01s)\n",
      "[TST] iter = 3900, cost = 498.805786, RMSE = 21.605677 (0.28s)\n",
      "[TRN] iter = 4000, cost = 2.64e+02, |grad| = 1.36e+03 (6.97e-01s)\n",
      "[TST] iter = 4000, cost = 499.274872, RMSE = 21.625996 (0.25s)\n",
      "[TRN] iter = 4100, cost = 2.66e+02, |grad| = 7.42e+02 (6.96e-01s)\n",
      "[TST] iter = 4100, cost = 497.999176, RMSE = 21.570738 (0.24s)\n",
      "[TRN] iter = 4200, cost = 2.99e+02, |grad| = 2.53e+03 (6.67e-01s)\n",
      "[TST] iter = 4200, cost = 491.588531, RMSE = 21.293062 (0.26s)\n",
      "[TRN] iter = 4300, cost = 2.62e+02, |grad| = 3.70e+02 (6.53e-01s)\n",
      "[TST] iter = 4300, cost = 499.287811, RMSE = 21.626556 (0.26s)\n",
      "[TRN] iter = 4400, cost = 2.65e+02, |grad| = 8.73e+02 (6.81e-01s)\n",
      "[TST] iter = 4400, cost = 494.242340, RMSE = 21.408012 (0.25s)\n",
      "[TRN] iter = 4500, cost = 2.56e+02, |grad| = 4.14e+02 (6.57e-01s)\n",
      "[TST] iter = 4500, cost = 493.276489, RMSE = 21.366177 (0.24s)\n",
      "[TRN] iter = 4600, cost = 2.59e+02, |grad| = 1.10e+03 (6.57e-01s)\n",
      "[TST] iter = 4600, cost = 497.635345, RMSE = 21.554979 (0.25s)\n",
      "[TRN] iter = 4700, cost = 2.51e+02, |grad| = 1.02e+03 (7.04e-01s)\n",
      "[TST] iter = 4700, cost = 499.741913, RMSE = 21.646225 (0.27s)\n",
      "[TRN] iter = 4800, cost = 2.52e+02, |grad| = 1.03e+03 (7.02e-01s)\n",
      "[TST] iter = 4800, cost = 495.080017, RMSE = 21.444296 (0.24s)\n",
      "[TRN] iter = 4900, cost = 2.56e+02, |grad| = 2.81e+03 (6.81e-01s)\n",
      "[TST] iter = 4900, cost = 497.800354, RMSE = 21.562126 (0.27s)\n",
      "[TRN] iter = 5000, cost = 2.46e+02, |grad| = 5.66e+02 (6.72e-01s)\n",
      "[TST] iter = 5000, cost = 497.435547, RMSE = 21.546326 (0.26s)\n",
      "[TRN] iter = 5100, cost = 2.43e+02, |grad| = 6.65e+02 (6.80e-01s)\n",
      "[TST] iter = 5100, cost = 492.930084, RMSE = 21.351171 (0.26s)\n",
      "[TRN] iter = 5200, cost = 2.42e+02, |grad| = 7.83e+02 (6.77e-01s)\n",
      "[TST] iter = 5200, cost = 500.044159, RMSE = 21.659317 (0.26s)\n",
      "[TRN] iter = 5300, cost = 2.54e+02, |grad| = 1.10e+03 (6.77e-01s)\n",
      "[TST] iter = 5300, cost = 505.414856, RMSE = 21.891947 (0.26s)\n",
      "[TRN] iter = 5400, cost = 2.38e+02, |grad| = 1.42e+03 (6.69e-01s)\n",
      "[TST] iter = 5400, cost = 498.725616, RMSE = 21.602203 (0.27s)\n",
      "[TRN] iter = 5500, cost = 2.40e+02, |grad| = 1.46e+03 (6.96e-01s)\n",
      "[TST] iter = 5500, cost = 498.079041, RMSE = 21.574198 (0.24s)\n",
      "[TRN] iter = 5600, cost = 2.35e+02, |grad| = 7.63e+02 (6.83e-01s)\n",
      "[TST] iter = 5600, cost = 496.168945, RMSE = 21.491463 (0.24s)\n",
      "[TRN] iter = 5700, cost = 2.52e+02, |grad| = 2.52e+03 (6.79e-01s)\n",
      "[TST] iter = 5700, cost = 494.458252, RMSE = 21.417364 (0.28s)\n",
      "[TRN] iter = 5800, cost = 2.36e+02, |grad| = 1.05e+03 (6.75e-01s)\n",
      "[TST] iter = 5800, cost = 511.798462, RMSE = 22.168453 (0.23s)\n",
      "[TRN] iter = 5900, cost = 2.34e+02, |grad| = 5.17e+02 (6.85e-01s)\n",
      "[TST] iter = 5900, cost = 499.314941, RMSE = 21.627731 (0.27s)\n",
      "[TRN] iter = 6000, cost = 2.32e+02, |grad| = 1.36e+03 (6.81e-01s)\n",
      "[TST] iter = 6000, cost = 498.311859, RMSE = 21.584282 (0.25s)\n",
      "[TRN] iter = 6100, cost = 2.31e+02, |grad| = 1.39e+03 (6.67e-01s)\n",
      "[TST] iter = 6100, cost = 499.229462, RMSE = 21.624029 (0.25s)\n",
      "[TRN] iter = 6200, cost = 2.34e+02, |grad| = 1.19e+03 (6.53e-01s)\n",
      "[TST] iter = 6200, cost = 509.653961, RMSE = 22.075563 (0.27s)\n",
      "[TRN] iter = 6300, cost = 2.26e+02, |grad| = 1.45e+03 (6.73e-01s)\n",
      "[TST] iter = 6300, cost = 511.754272, RMSE = 22.166538 (0.24s)\n",
      "[TRN] iter = 6400, cost = 2.25e+02, |grad| = 1.19e+03 (7.03e-01s)\n",
      "[TST] iter = 6400, cost = 502.439056, RMSE = 21.763052 (0.28s)\n",
      "[TRN] iter = 6500, cost = 2.28e+02, |grad| = 1.22e+03 (6.61e-01s)\n",
      "[TST] iter = 6500, cost = 507.944977, RMSE = 22.001539 (0.27s)\n",
      "[TRN] iter = 6600, cost = 2.21e+02, |grad| = 6.53e+02 (6.93e-01s)\n",
      "[TST] iter = 6600, cost = 504.578796, RMSE = 21.855734 (0.27s)\n",
      "[TRN] iter = 6700, cost = 2.24e+02, |grad| = 8.85e+02 (6.69e-01s)\n",
      "[TST] iter = 6700, cost = 506.142456, RMSE = 21.923464 (0.27s)\n",
      "[TRN] iter = 6800, cost = 2.43e+02, |grad| = 1.49e+03 (6.82e-01s)\n",
      "[TST] iter = 6800, cost = 514.720703, RMSE = 22.295029 (0.27s)\n",
      "[TRN] iter = 6900, cost = 2.19e+02, |grad| = 7.30e+02 (6.57e-01s)\n",
      "[TST] iter = 6900, cost = 505.827240, RMSE = 21.909811 (0.24s)\n",
      "[TRN] iter = 7000, cost = 2.22e+02, |grad| = 7.85e+02 (6.88e-01s)\n",
      "[TST] iter = 7000, cost = 504.051086, RMSE = 21.832876 (0.23s)\n",
      "[TRN] iter = 7100, cost = 2.15e+02, |grad| = 7.64e+02 (6.85e-01s)\n",
      "[TST] iter = 7100, cost = 507.585175, RMSE = 21.985954 (0.26s)\n",
      "[TRN] iter = 7200, cost = 2.16e+02, |grad| = 1.26e+03 (6.86e-01s)\n",
      "[TST] iter = 7200, cost = 504.318542, RMSE = 21.844460 (0.25s)\n",
      "[TRN] iter = 7300, cost = 2.19e+02, |grad| = 1.26e+03 (6.81e-01s)\n",
      "[TST] iter = 7300, cost = 511.018890, RMSE = 22.134686 (0.27s)\n",
      "[TRN] iter = 7400, cost = 2.16e+02, |grad| = 5.82e+02 (7.01e-01s)\n",
      "[TST] iter = 7400, cost = 506.459045, RMSE = 21.937176 (0.25s)\n",
      "[TRN] iter = 7500, cost = 2.16e+02, |grad| = 7.77e+02 (6.74e-01s)\n",
      "[TST] iter = 7500, cost = 504.880371, RMSE = 21.868797 (0.25s)\n",
      "[TRN] iter = 7600, cost = 2.15e+02, |grad| = 2.14e+03 (6.92e-01s)\n",
      "[TST] iter = 7600, cost = 510.706573, RMSE = 22.121157 (0.28s)\n",
      "[TRN] iter = 7700, cost = 2.18e+02, |grad| = 1.28e+03 (6.66e-01s)\n",
      "[TST] iter = 7700, cost = 503.350159, RMSE = 21.802515 (0.25s)\n",
      "[TRN] iter = 7800, cost = 2.09e+02, |grad| = 1.57e+03 (6.86e-01s)\n",
      "[TST] iter = 7800, cost = 511.391083, RMSE = 22.150806 (0.26s)\n",
      "[TRN] iter = 7900, cost = 2.07e+02, |grad| = 8.08e+02 (6.48e-01s)\n",
      "[TST] iter = 7900, cost = 516.280396, RMSE = 22.362585 (0.27s)\n",
      "[TRN] iter = 8000, cost = 2.15e+02, |grad| = 1.11e+03 (6.73e-01s)\n",
      "[TST] iter = 8000, cost = 509.772308, RMSE = 22.080690 (0.25s)\n",
      "[TRN] iter = 8100, cost = 2.05e+02, |grad| = 6.70e+02 (6.88e-01s)\n",
      "[TST] iter = 8100, cost = 511.687347, RMSE = 22.163639 (0.25s)\n",
      "[TRN] iter = 8200, cost = 2.04e+02, |grad| = 1.64e+03 (6.73e-01s)\n",
      "[TST] iter = 8200, cost = 515.301086, RMSE = 22.320168 (0.26s)\n",
      "[TRN] iter = 8300, cost = 2.03e+02, |grad| = 7.57e+02 (6.62e-01s)\n",
      "[TST] iter = 8300, cost = 514.967773, RMSE = 22.305731 (0.27s)\n",
      "[TRN] iter = 8400, cost = 2.04e+02, |grad| = 5.61e+02 (6.74e-01s)\n",
      "[TST] iter = 8400, cost = 512.595032, RMSE = 22.202955 (0.25s)\n",
      "[TRN] iter = 8500, cost = 2.11e+02, |grad| = 2.17e+03 (6.77e-01s)\n",
      "[TST] iter = 8500, cost = 516.012024, RMSE = 22.350962 (0.24s)\n",
      "[TRN] iter = 8600, cost = 2.42e+02, |grad| = 5.32e+02 (7.02e-01s)\n",
      "[TST] iter = 8600, cost = 491.042389, RMSE = 21.269407 (0.27s)\n",
      "[TRN] iter = 8700, cost = 2.11e+02, |grad| = 2.27e+03 (6.73e-01s)\n",
      "[TST] iter = 8700, cost = 520.178650, RMSE = 22.531437 (0.25s)\n",
      "[TRN] iter = 8800, cost = 2.01e+02, |grad| = 1.22e+03 (6.74e-01s)\n",
      "[TST] iter = 8800, cost = 513.738281, RMSE = 22.252476 (0.25s)\n",
      "[TRN] iter = 8900, cost = 2.02e+02, |grad| = 1.50e+03 (6.84e-01s)\n",
      "[TST] iter = 8900, cost = 510.987396, RMSE = 22.133322 (0.23s)\n",
      "[TRN] iter = 9000, cost = 1.98e+02, |grad| = 1.49e+03 (6.79e-01s)\n",
      "[TST] iter = 9000, cost = 515.818542, RMSE = 22.342581 (0.26s)\n",
      "[TRN] iter = 9100, cost = 2.01e+02, |grad| = 9.99e+02 (6.86e-01s)\n",
      "[TST] iter = 9100, cost = 517.551270, RMSE = 22.417633 (0.24s)\n",
      "[TRN] iter = 9200, cost = 1.94e+02, |grad| = 6.35e+02 (6.73e-01s)\n",
      "[TST] iter = 9200, cost = 519.536743, RMSE = 22.503635 (0.26s)\n",
      "[TRN] iter = 9300, cost = 1.92e+02, |grad| = 4.84e+02 (6.88e-01s)\n",
      "[TST] iter = 9300, cost = 516.739990, RMSE = 22.382494 (0.27s)\n",
      "[TRN] iter = 9400, cost = 1.99e+02, |grad| = 8.38e+02 (6.64e-01s)\n",
      "[TST] iter = 9400, cost = 513.666260, RMSE = 22.249355 (0.25s)\n",
      "[TRN] iter = 9500, cost = 1.94e+02, |grad| = 8.74e+02 (6.70e-01s)\n",
      "[TST] iter = 9500, cost = 519.333862, RMSE = 22.494846 (0.26s)\n",
      "[TRN] iter = 9600, cost = 2.92e+02, |grad| = 4.67e+03 (6.51e-01s)\n",
      "[TST] iter = 9600, cost = 485.048920, RMSE = 21.009802 (0.25s)\n",
      "[TRN] iter = 9700, cost = 1.96e+02, |grad| = 6.58e+02 (6.73e-01s)\n",
      "[TST] iter = 9700, cost = 517.489075, RMSE = 22.414940 (0.27s)\n",
      "[TRN] iter = 9800, cost = 1.89e+02, |grad| = 4.97e+02 (6.61e-01s)\n",
      "[TST] iter = 9800, cost = 522.250183, RMSE = 22.621166 (0.24s)\n",
      "[TRN] iter = 9900, cost = 1.96e+02, |grad| = 1.69e+03 (7.17e-01s)\n",
      "[TST] iter = 9900, cost = 524.063171, RMSE = 22.699696 (0.25s)\n"
     ]
    }
   ],
   "source": [
    "ord_col = 5\n",
    "n_test_samples = np.sum(Otest)\n",
    "\n",
    "learning_obj = Train_test_matrix_completion(M, Lcol, Odata, Otraining, Otest, \n",
    "                                                    initial_W, initial_H,\n",
    "                                                    order_chebyshev_col = ord_col, \n",
    "                                                    gamma=1e2, gamma_W=1e-2,\n",
    "                                                    learning_rate=1e-3)\n",
    "\n",
    "num_iter_test = 100\n",
    "num_total_iter_training = 10000#int(1e8)\n",
    "\n",
    "num_iter = 0\n",
    "\n",
    "list_training_loss = list()\n",
    "list_training_norm_grad = list()\n",
    "list_test_pred_error = list()\n",
    "list_predictions = list()\n",
    "list_X = list()\n",
    "\n",
    "list_training_times = list()\n",
    "list_test_times = list()\n",
    "list_grad_X = list()\n",
    "list_RMSE = []\n",
    "\n",
    "list_X_evolutions = list()\n",
    "\n",
    "path_log = '../../../../log/tmp.txt'#'../../log/supervisd_approach_norm_acc.txt'\n",
    "\n",
    "if (os.path.isfile(path_log) == True):\n",
    "    os.remove(path_log)\n",
    "\n",
    "with open(path_log,'a+') as f:\n",
    "    for k in range(num_iter, num_total_iter_training):\n",
    "\n",
    "                tic = time.time()\n",
    "                _, current_training_loss, norm_grad, X_grad = learning_obj.session.run([learning_obj.optimizer, learning_obj.loss, \n",
    "                                                                                        learning_obj.norm_grad, learning_obj.var_grad]) \n",
    "                training_time = time.time() - tic\n",
    "\n",
    "                list_training_loss.append(current_training_loss)\n",
    "                list_training_norm_grad.append(norm_grad)\n",
    "                list_training_times.append(training_time)\n",
    "                #list_grad_X.append(X_grad)\n",
    "\n",
    "                if (np.mod(num_iter, num_iter_test)==0):\n",
    "                    msg = \"[TRN] iter = %03i, cost = %3.2e, |grad| = %.2e (%3.2es)\" \\\n",
    "                                    % (num_iter, list_training_loss[-1], list_training_norm_grad[-1], training_time)\n",
    "                    print msg\n",
    "                    #f.write(msg+'\\n')\n",
    "\n",
    "                    #Test Code\n",
    "                    tic = time.time()\n",
    "                    pred_error, preds, X = learning_obj.session.run([learning_obj.predictions_error, learning_obj.predictions,\n",
    "                                                                             learning_obj.norm_X]) \n",
    "                    #c_X_evolutions = learning_obj.session.run(learning_obj.list_X)\n",
    "                    #list_X_evolutions.append(c_X_evolutions)\n",
    "\n",
    "                    test_time = time.time() - tic\n",
    "\n",
    "                    list_test_pred_error.append(pred_error)\n",
    "                    #list_predictions.append(preds)\n",
    "                    #list_X.append(X)\n",
    "                    list_test_times.append(test_time)\n",
    "                    RMSE = np.sqrt(np.square(pred_error)/n_test_samples)\n",
    "                    list_RMSE.append(RMSE)\n",
    "                    msg =  \"[TST] iter = %03i, cost = %f, RMSE = %f (%03.2fs)\" % (num_iter, list_test_pred_error[-1], RMSE, test_time)\n",
    "                    print msg\n",
    "\n",
    "                num_iter += 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Best predictions at iter: 9700 (error: 517.489075)\n",
      "RMSE: 22.414940\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "\"pp = PdfPages('../../pdf/losses/corrected_gamma_best_iter/supervised_approach_original_training_set_40k_iter.pdf')\\nplt.savefig(pp, format='pdf')\\npp.close()\""
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\nk7/+6+4v/WMfu+1fxzXXJL/yK90U2YYNyQ/+YPL4xyf511ckB39h21+YFVclqAQAAFbeeeclr3pV\n9/iAA5IzzugCod13Tw4/fLprm09ryWWXJaef3oVzl1+eHHVUMjubPOEJyc47L3ztbrslL3tZ8tKX\ndiXvL3lJd+y447rXWM6gaNOmLjf46le70Ovaa7tC+eW2cWPym7+ZfPKTyT//c/LgBy//Pfqsn5Ne\na/fIjbcsPem1pdNr48bkL/8yOfDA7hvqM5/ppqu2ZlRw9eruL9/P/VzykY90hXLPeU7yghck11+/\n9V/DP/5jcthhyU/8RPeX+3736765Tz01yad/K1+/5CFb/6KsuC2dXhWhFwAAsLI2bUouvDB5xCNu\nP3booV2/1y/9UvJv/za9tc313e8mH/1ocuyxXTD3hCd0QyV//MfdMMi73tUFdYsFXnOtWdMFUpdc\nkvyv/9X9fH/QQd2Ayrjd3ou55ZbkWc/qftb/yEe6APGBD0y+9rXl7wE//fQuozjnHIHXtuhl6LX7\nPXZfcnvjmjXdN9bppycPfWjygQ90QdPf/m1y//vfvftXJUcf3X2D7bFH8pCHdN+kmzcvfe33vtd9\no7/kJclpp3Vp9ty3Hd1//yRHPT/nvfV3ct11d2+dTN5tm29LotAeAABYeZdckuy3X/dz6VyPeUxy\n0knd9NNFF01nbV/5SvL2t3fbE/fZp5uS+sEf7AK5K6/siuF/+qfHD7rms9NO3df4b//WBV5///fJ\nAx7QbRFcquN7Id/5TvL0p3dTY6efnuyyS3d81aouWPv857d9vfO54ILu92j33Zf3dYeil6HXvXe5\nd2747g2LnrN2bRcs/eEfdkV4Z5/dTVYtp913T970pq73613v6t5VYrF/UC69tCveu+aaLo1fcGvk\nAWfmh9Z9PL/4i8ltty3vmllet7XuD2hzGyPxBACAAWktecMbuqDgP/5j2quZvssv7wYxltN553Ud\nV/N5ylO68OepT+2mqiZt06auY+tlL+v+zH/8x7san1/5lW6L4D//c7cN8ZBDukGS5VSV/NRPdVNZ\nH/5w1212wAHdjq9bbx3/df7rv7qJs/32S97//uQe97jj8w996PKHXhde2E3nsW16GXrtveve+dp3\nvrboOUcf3RXdXXhh900+ycqlhz88+X//L3n+85MnPSn5vd9Lvv3t259vresAe9zjur26p5229NbK\n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\nREREROTnK3bFZOZnEp8Wz/ZD2zEzNiVvYlPyJqJDo2lVtxUPnP9AudAytzDXVzm4fN9ydh/Zzeur\nXye2QSz39LyHWzrfQkJ6Ahn5GYQHh5cLWQDSctNIy03juaXP0TC0IRuTN/L9ke8JrxnOhqQNvk0f\nDKN13dakZqeWqfAD6BbdjbjUOJpFNOPG2Bs5kHGA2jVq89rq13zn1AmpQ1puGgBto9oysO1ARnQf\nQZPwJmTmZzJ983Qe/frRE36e7upxF59u+5SU7BSiQ6NJyvphN8Z7zruHl1e9XOb8mbfM5Or2V5dp\nO5p3lIV7FvLSypdIyUphfdL6E77nwHYD6RvTl071OzGo4w8bdqRkpTBh2QSubn+1pzrrOFbctcK3\npty1Ha7ls22fAfg2U6iIFrI/Ayj0EhEREREREfFvGXkZBAcGk5qdyvqk9dQJqcM5jc8hIT2BlOwU\nwoPDiU+PJzM/k/DgcObsmkNqdipRtaK4MfZGLm55MZ9s/YSUrBQahzemX6t+ZSr2jlVUXITDcTTv\nKGm5aaxNXEuRKyIjL4P49HiSs5KJqBnB199/Ta0atejRqAe/jv01F7W4iMz8TAqLC0nKTKJpRNNT\nWrssvyif4MBgdhzawafbPiUuJY7k7GRa1WlFbINYFuxZwLTN0wDP5hIRNSNoXbc1c3bNKXOf9254\njwFtBlCvdr1y75GWm8bD8x7mtdWv0aZuG3Yd2UXeWE/1ZUUUep0BFHqJiIiIiIiIyP+C1OxU0nPT\nOZh5kB2Hd3Bxi4t9lXMlwdnJFLtiDDvpNGOFXmcAhV4iIiIiIiIiIqdXdQy9Tr7ymYiIiIiIiIiI\nSDWj0EtERERERERERPyOQi8REREREREREfE7Cr1ERERERERERMTvKPQSERERERERERG/o9BLRERE\nRERERET8jkIvERERERERERHxOwq9RERERERERETE7yj0EhERERERERERv6PQS0RERERERERE/I5C\nLxERERERERER8TsKvURERERERERExO8o9BIREREREREREb+j0EtERERERERERPyOQi8RERERERER\nEfE7Cr1ERERERERERMTvKPQSERERERERERG/o9BLRERERERERET8jkIvERERERERERHxOwq9RERE\nRERERETE7yj0EhERERERERERv6PQS0RERERERERE/I5CLxERERERERER8TsKvURERERERERExO8o\n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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7fd15a438c10>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "fig, ax1 = plt.subplots(figsize=(20,10))\n",
    "\n",
    "ax2 = ax1.twinx()\n",
    "ax1.plot(np.arange(len(list_training_loss)), list_training_loss, 'g-')\n",
    "ax2.plot(np.arange(len(list_test_pred_error))*num_iter_test, list_test_pred_error, 'b-')\n",
    "\n",
    "ax1.set_xlabel('Iteration')\n",
    "ax1.set_ylabel('Training loss', color='g')\n",
    "ax2.set_ylabel('Test loss', color='b')\n",
    "\n",
    "#best_iter = len(list_training_loss)\n",
    "best_iter = (np.where(np.asarray(list_training_loss)==np.min(list_training_loss))[0][0]//num_iter_test)*num_iter_test\n",
    "best_pred_error = list_test_pred_error[best_iter//num_iter_test]\n",
    "print 'Best predictions at iter: %d (error: %f)' % (best_iter, best_pred_error)\n",
    "RMSE = np.sqrt(np.square(best_pred_error)/np.sum(Otest))\n",
    "print 'RMSE: %f' % RMSE\n",
    "\"\"\"pp = PdfPages('../../pdf/losses/corrected_gamma_best_iter/supervised_approach_original_training_set_40k_iter.pdf')\n",
    "plt.savefig(pp, format='pdf')\n",
    "pp.close()\"\"\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [],
   "source": [
    "with learning_obj.graph.as_default():\n",
    "\n",
    "    oSaver = tf.train.Saver()\n",
    "\n",
    "    oSess = learning_obj.session\n",
    "    oSaver.save(oSess, './dumps/backup_supervised_approach/backup.dump')  #filename ends with .ckpt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['./dumps/results_supervised_approach/results.dump']"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "joblib.dump([list_training_loss, list_test_pred_error, num_iter_test], './dumps/results_supervised_approach/results.dump')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true,
    "deletable": true,
    "editable": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 2",
   "language": "python",
   "name": "python2"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
